package com.cq.hd.member.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cq.hd.common.constant.Constant;
import com.cq.hd.common.constant.HfConstant;
import com.cq.hd.common.constant.RedisKeyConstant;
import com.cq.hd.common.entity.UserInfo;
import com.cq.hd.common.entity.hf.HfAgentUserEnterApply;
import com.cq.hd.common.entity.hf.HfAgentUserSignCreate;
import com.cq.hd.common.enums.ResponseEnums;
import com.cq.hd.common.enums.biz.*;
import com.cq.hd.common.response.Throw;
import com.cq.hd.common.utils.*;
import com.cq.hd.member.api.dto.*;
import com.cq.hd.member.api.vo.*;
import com.cq.hd.member.biz.SmsBiz;
import com.cq.hd.member.config.LockUtils;
import com.cq.hd.member.mapper.*;
import com.cq.hd.member.po.*;
import com.cq.hd.member.service.TbAgentBindApplyService;
import com.cq.hd.member.service.TbAgentEnterApplyService;
import com.cq.hd.member.service.TbUserBusinessService;
import com.cq.hd.system.api.HfApi;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.interceptor.DefaultTransactionAttribute;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.text.MessageFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 * 经纪人入驻申请记录表 服务实现类
 * </p>
 *
 * @author mYunYu
 * @since 2024-01-18
 */
@Slf4j
@Service
public class TbAgentEnterApplyServiceImpl extends ServiceImpl<TbAgentEnterApplyMapper, TbAgentEnterApplyPo> implements TbAgentEnterApplyService {

    @Autowired
    private TbBusinessMapper businessMapper;

    @Autowired
    private TbAppUserMapper appUserMapper;

    @Autowired
    private TbBusinessAgentMapper businessAgentMapper;

    @Autowired
    private TbBusinessGroupMapper businessGroupMapper;

    @Autowired
    private TbBusinessAgentCommissionRecordMapper businessAgentCommissionRecordMapper;

    @Autowired
    private TbBusinessAgentBindRecordMapper businessAgentBindRecordMapper;

    @Autowired
    private TbAgentBankUpdateRecordMapper agentBankUpdateRecordMapper;

    @Autowired
    private TbWithdrawalBillMapper withdrawalBillMapper;

    @Autowired
    private PlatformTransactionManager transactionManager;

    @Autowired
    private RedisUtil redisUtil;

    @Autowired
    private HfApi hfApi;

    @Autowired
    private SmsBiz smsBiz;

    @Autowired
    private TbUserBusinessService userBusinessService;

    @Override
    public PreAgentApplyMerchantVo preApply(PreAgentEnterApplyDto preAgentApplyMerchantDto) {
        PreAgentApplyMerchantVo preAgentApplyMerchantVo = new PreAgentApplyMerchantVo();

        String settleCode = preAgentApplyMerchantDto.getSettleCode();
        Long userId = preAgentApplyMerchantDto.getUserId();
        if (StringUtils.isBlank(settleCode)) {
            Throw.isBusinessException("邀请码不能为空");
        }

        if (userId == null || userId <= 0) {
            Throw.isBusinessException(ResponseEnums.USER_ACCESS_DENIED);
        }

        // 根据邀请码查询商家数据
        List<TbBusinessPo> businessPos = businessMapper.selectList(new QueryWrapper<TbBusinessPo>().eq("del_state", 0)
                .eq("state", 1).eq("invite_code", settleCode));
        if (CollectionUtils.isEmpty(businessPos)) {
            Throw.isBusinessException("邀请码错误[3]");
        }

        TbBusinessPo businessPo = businessPos.get(0);
        Long id = businessPo.getId();

        // 根据用户id查询用户数据，判断是否是经纪人
        TbAppUserPo tbAppUserPo = appUserMapper.selectById(userId);
        if (tbAppUserPo == null || tbAppUserPo.getDelState() != 0) {
            Throw.isBusinessException(ResponseEnums.USER_NOT_FOUND);
        }

        if (businessPo.getUserId().equals(userId)) {
            log.error("受邀用户与商家是同一个用户，userId：{}", userId);
            Throw.isBusinessException("不能成为商家自己的经纪人");
        }

        // 查询经纪人已经入驻的商家的状态
        Integer agentEnterState = AgentEnterStateEnum.WAIT_ENTER.getValue();

        TbBusinessAgentPo businessAgentPo = null;
        List<TbBusinessAgentPo> tbBusinessAgentPos = businessAgentMapper.selectList(new QueryWrapper<TbBusinessAgentPo>()
                .eq("user_id", userId));
        if (!CollectionUtils.isEmpty(tbBusinessAgentPos)) {
            agentEnterState = tbBusinessAgentPos.get(0).getState();

            for (TbBusinessAgentPo tbBusinessAgentPo : tbBusinessAgentPos) {
                if (tbBusinessAgentPo.getDelState() == 0 && tbBusinessAgentPo.getBusinessId().equals(id)) {
                    businessAgentPo = tbBusinessAgentPo;
                    break;
                }
            }

            if (businessAgentPo != null) {
                Throw.isBusinessException(ResponseEnums.BINDED_BUSINESS);
            }
        }

        // 如果是，则直接绑定
        // 如果不是，跳转到开户页

        // 是否是经纪人(1-不是，2-是)
        Integer agentState = tbAppUserPo.getAgentState();
        if (agentState == null || agentState == 1) {
            // 是否要跳转到开户页，1-是，2-否
            preAgentApplyMerchantVo.setState(1);
            return preAgentApplyMerchantVo;
        }

        // 查找该商家的默认分组
        TbBusinessGroupPo businessGroupPo = businessGroupMapper.getDefaultGroup(id);
        LocalDateTime now = LocalDateTime.now();

        TransactionStatus transaction = transactionManager.getTransaction(new DefaultTransactionAttribute());

        try {
            if (businessAgentPo != null && businessAgentPo.getId() != null) {
                // 如果解绑之后再次绑定，之前设置的分组和佣金都需要重新设置
                businessAgentPo.setCommissionRate(BigDecimal.ZERO);
                // 更新状态
                businessAgentPo.setDelState(0);
                businessAgentPo.setUpdateTime(now);
                int update = businessAgentMapper.updateBind(businessAgentPo);
                if (update == 0) {
                    Throw.isBusinessException("受邀失败");
                }

                // 新增专属佣金设置记录
                TbBusinessAgentCommissionRecordPo tbBusinessAgentCommissionRecordPo = new TbBusinessAgentCommissionRecordPo();
                tbBusinessAgentCommissionRecordPo.setBusinessId(businessAgentPo.getBusinessId());
                tbBusinessAgentCommissionRecordPo.setUserId(businessAgentPo.getUserId());
                tbBusinessAgentCommissionRecordPo.setCommissionRate(businessAgentPo.getCommissionRate());
                tbBusinessAgentCommissionRecordPo.setCreateBusinessId(businessAgentPo.getBusinessId());
                tbBusinessAgentCommissionRecordPo.setCreateTime(now);
                tbBusinessAgentCommissionRecordPo.setUpdateTime(now);
                int insert = businessAgentCommissionRecordMapper.insert(tbBusinessAgentCommissionRecordPo);
                if (insert == 0) {
                    Throw.isBusinessException("受邀失败");
                }
            } else {
                TbBusinessAgentPo tbBusinessAgentPo = new TbBusinessAgentPo();
                tbBusinessAgentPo.setUserId(userId);
                tbBusinessAgentPo.setBusinessId(id);
                tbBusinessAgentPo.setTotalOrderCount(0);
                tbBusinessAgentPo.setTotalOrderAmt(BigDecimal.ZERO);
                tbBusinessAgentPo.setRelationBusinessCount(1);
                tbBusinessAgentPo.setTotalCommission(BigDecimal.ZERO);
                tbBusinessAgentPo.setTotalWithdrawalCommission(BigDecimal.ZERO);
                tbBusinessAgentPo.setState(agentEnterState);
                tbBusinessAgentPo.setCreateTime(now);
                int insert = businessAgentMapper.insert(tbBusinessAgentPo);
                if (insert == 0) {
                    Throw.isBusinessException("受邀失败");
                }
            }

            // 添加商家经纪人绑定记录
            TbBusinessAgentBindRecordPo tbBusinessAgentBindRecordPo = new TbBusinessAgentBindRecordPo();
            tbBusinessAgentBindRecordPo.setUserId(userId);
            tbBusinessAgentBindRecordPo.setBusinessId(id);
            tbBusinessAgentBindRecordPo.setBindTime(now);
            tbBusinessAgentBindRecordPo.setCreateTime(now);
            int insert = businessAgentBindRecordMapper.insert(tbBusinessAgentBindRecordPo);
            if (insert <= 0) {
                Throw.isBusinessException("受邀失败");
            }

            transactionManager.commit(transaction);
        } catch (Exception e) {
            //回滚事务
            transactionManager.rollback(transaction);
            log.error("<经纪人直接绑定商家>事务异常回滚", e);
            Throw.isBusinessException("受邀失败");
        }

        preAgentApplyMerchantVo.setState(2);
        return preAgentApplyMerchantVo;
    }

    @Override
    public Boolean bind(BusinessAgentBindDto businessAgentBindDto) {
        String code = businessAgentBindDto.getCode();
        Long userId = businessAgentBindDto.getUserId();
        if (userId == null || StringUtils.isBlank(code)) {
            Throw.isBusinessException("邀请链接错误");
        }

        String personName = businessAgentBindDto.getPersonName();
        if (StringUtils.isBlank(personName)) {
            Throw.isBusinessException("请输入姓名");
        }

        String certNo = businessAgentBindDto.getCertNo();
        if (StringUtils.isBlank(certNo)) {
            Throw.isBusinessException("请输入身份证号");
        }

        Integer certValidityType = businessAgentBindDto.getCertValidityType();
        if (certValidityType == null || CertValidityTypeEnum.typeOfValue(certValidityType) == null) {
            Throw.isBusinessException("请选择证件有效期");
        }

        String certBeginDate = businessAgentBindDto.getCertBeginDate();
        if (CertValidityTypeEnum.NO.getValue().equals(certValidityType)) {
            String certEndDate = businessAgentBindDto.getCertEndDate();
            if (StringUtils.isBlank(certBeginDate)) {
                Throw.isBusinessException("请选择证件有效期开始日期");
            }

            if (StringUtils.isBlank(certEndDate)) {
                Throw.isBusinessException("请选择证件有效期截止日期");
            }

            LocalDate legalCertBeginLocalDate = null;
            LocalDate legalCertEndLocalDate = null;
            try {
                legalCertBeginLocalDate = LocalDateUtil.toLocalDate(certBeginDate, Constant.YYYY_MM_DD);
            } catch (Exception e) {
                Throw.isBusinessException("证件有效期开始日期选择错误");
            }

            try {
                legalCertEndLocalDate = LocalDateUtil.toLocalDate(certEndDate, Constant.YYYY_MM_DD);
            } catch (Exception e) {
                Throw.isBusinessException("证件有效期截止日期选择错误");
            }

            if (legalCertEndLocalDate.compareTo(legalCertBeginLocalDate) <= 0) {
                Throw.isBusinessException("证件有效期截止日期必须大于开始日期");
            }
        } else {
            // 如果是长期有效，法人证件有效期开始日期也不能为空
            if (StringUtils.isBlank(certBeginDate)) {
                Throw.isBusinessException("请选择证件有效期开始日期");
            }

            LocalDate legalCertBeginLocalDate = null;
            try {
                legalCertBeginLocalDate = LocalDateUtil.toLocalDate(certBeginDate, Constant.YYYY_MM_DD);
            } catch (Exception e) {
                Throw.isBusinessException("证件有效期开始日期选择错误");
            }
        }

        TbAppUserPo tbAppUserPo = appUserMapper.selectById(userId);
        if (tbAppUserPo == null || tbAppUserPo.getDelState() != 0) {
            Throw.isBusinessException("未找到用户数据");
        }

        List<TbBusinessPo> businessPos = businessMapper.selectList(new QueryWrapper<TbBusinessPo>().eq("del_state", 0)
                .eq("invite_code", code));
        if (CollectionUtils.isEmpty(businessPos)) {
            Throw.isBusinessException("未找到商家");
        }

        TbBusinessPo tbBusinessPo = businessPos.get(0);
        Long id = tbBusinessPo.getId();
        String hfMerchantNo = tbBusinessPo.getHfMerchantNo();

        if (tbBusinessPo.getUserId().equals(userId)) {
            log.error("受邀用户与商家是同一个用户，userId：{}", userId);
            Throw.isBusinessException("不能成为商家自己的经纪人");
        }

        TbBusinessAgentPo businessAgentPo = new TbBusinessAgentPo();
        List<TbBusinessAgentPo> tbBusinessAgentPos = businessAgentMapper.selectList(new QueryWrapper<TbBusinessAgentPo>()
                .eq("del_state", 0)
                .eq("user_id", userId).eq("business_id", id));
        if (!CollectionUtils.isEmpty(tbBusinessAgentPos)) {
            boolean exist = false;
            for (TbBusinessAgentPo tbBusinessAgentPo : tbBusinessAgentPos) {
                if (tbBusinessAgentPo.getDelState() == 0) {
                    exist = true;
                    break;
                }
            }

            if (exist) {
                Throw.isBusinessException(ResponseEnums.BINDED_BUSINESS);
            }

            businessAgentPo = tbBusinessAgentPos.get(0);
        }

        boolean firstEnter = false;
        String getHfId = tbAppUserPo.getHfId();
        // 是否是经纪人(1-不是，2-是)
        if (tbAppUserPo.getAgentState() == 1 && !StringUtils.isBlank(hfMerchantNo) && StringUtils.isBlank(getHfId)) {
            //  调用汇付个人用户基本信息开户接口
            HfAgentUserEnterApply hfAgentUserEnterApply = new HfAgentUserEnterApply();
            hfAgentUserEnterApply.setPersonName(businessAgentBindDto.getPersonName());
            hfAgentUserEnterApply.setCertNo(businessAgentBindDto.getCertNo());
            hfAgentUserEnterApply.setCertValidityType(businessAgentBindDto.getCertValidityType());
            hfAgentUserEnterApply.setCertBeginDate(businessAgentBindDto.getCertBeginDate());
            hfAgentUserEnterApply.setCertEndDate(businessAgentBindDto.getCertEndDate());
            hfAgentUserEnterApply.setMobileNo(tbAppUserPo.getMobile());
            JSONObject jsonObject = hfApi.agentUserInvite(hfAgentUserEnterApply).unpack();
            if (jsonObject == null) {
                Throw.isBusinessException("绑定失败，请联系客服");
            }

            JSONObject dataJSONObject = jsonObject.getJSONObject("data");
            String respCode = dataJSONObject.getString("resp_code");
            String respDesc = dataJSONObject.getString("resp_desc");
            if (!"00000000".equals(respCode) && !"00000100".equals(respCode) && !"00000102".equals(respCode) && !"90000000".equals(respCode)) {
                Throw.isBusinessException(respDesc);
            }

            String hfId = dataJSONObject.getString("huifu_id");
            if (!StringUtils.isBlank(hfId)) {
                tbAppUserPo.setHfId(hfId);
            }
            tbAppUserPo.setRealName(businessAgentBindDto.getPersonName());
            tbAppUserPo.setCertNo(businessAgentBindDto.getCertNo());
            tbAppUserPo.setCertValidityType(businessAgentBindDto.getCertValidityType());
            tbAppUserPo.setCertBeginDate(businessAgentBindDto.getCertBeginDate());
            tbAppUserPo.setCertEndDate(businessAgentBindDto.getCertEndDate());

            firstEnter = true;
        }

        Long businessGroupId = businessAgentBindDto.getBusinessGroupId();
        // 如果没有传分组id，查找该商家的默认分组
        if (businessGroupId == null || businessGroupId < 1) {
            TbBusinessGroupPo businessGroupPo = businessGroupMapper.getDefaultGroup(id);
            businessGroupId = businessGroupPo.getId();
        }
        LocalDateTime now = LocalDateTime.now();

        TransactionStatus transaction = transactionManager.getTransaction(new DefaultTransactionAttribute());

        try {
            if (businessAgentPo != null && businessAgentPo.getId() != null) {
                // 如果解绑之后再次绑定，之前设置的分组和佣金都需要重新设置
                businessAgentPo.setGroupId(businessGroupId);
                businessAgentPo.setCommissionRate(BigDecimal.ZERO);
                // 更新状态
                businessAgentPo.setDelState(0);
                businessAgentPo.setUpdateTime(now);
                int update = businessAgentMapper.updateBind(businessAgentPo);
                if (update == 0) {
                    log.error("经纪人绑定商家失败,解绑之后再次绑定,修改经纪人商家关联记录状态失败,userId:{}, businessId:{}", userId, id);
                    Throw.isBusinessException("受邀失败");
                }

                // 新增专属佣金设置记录
                TbBusinessAgentCommissionRecordPo tbBusinessAgentCommissionRecordPo = new TbBusinessAgentCommissionRecordPo();
                tbBusinessAgentCommissionRecordPo.setBusinessId(businessAgentPo.getBusinessId());
                tbBusinessAgentCommissionRecordPo.setUserId(businessAgentPo.getUserId());
                tbBusinessAgentCommissionRecordPo.setCommissionRate(businessAgentPo.getCommissionRate());
                tbBusinessAgentCommissionRecordPo.setCreateBusinessId(businessAgentPo.getBusinessId());
                tbBusinessAgentCommissionRecordPo.setCreateTime(now);
                tbBusinessAgentCommissionRecordPo.setUpdateTime(now);
                int insert = businessAgentCommissionRecordMapper.insert(tbBusinessAgentCommissionRecordPo);
                if (insert == 0) {
                    log.error("经纪人绑定商家失败,添加专属佣金设置记录失败,userId:{}, businessId:{}", userId, id);
                    Throw.isBusinessException("受邀失败");
                }
            } else {
                TbBusinessAgentPo tbBusinessAgentPo = new TbBusinessAgentPo();
                tbBusinessAgentPo.setUserId(userId);
                tbBusinessAgentPo.setBusinessId(id);
                tbBusinessAgentPo.setGroupId(businessGroupId);
                tbBusinessAgentPo.setTotalOrderCount(0);
                tbBusinessAgentPo.setTotalOrderAmt(BigDecimal.ZERO);
                tbBusinessAgentPo.setRelationBusinessCount(1);
                tbBusinessAgentPo.setTotalCommission(BigDecimal.ZERO);
                tbBusinessAgentPo.setTotalWithdrawalCommission(BigDecimal.ZERO);
                tbBusinessAgentPo.setState(AgentEnterStateEnum.WAIT_ENTER.getValue());
                tbBusinessAgentPo.setCreateTime(now);
                int insert = businessAgentMapper.insert(tbBusinessAgentPo);
                if (insert == 0) {
                    log.error("经纪人绑定商家失败,添加经纪人商家关联记录失败,userId:{}, businessId:{}", userId, id);
                    Throw.isBusinessException("受邀失败");
                }

                // 添加经纪人入驻记录
                TbAgentEnterApplyPo tbAgentEnterApplyPo = new TbAgentEnterApplyPo();
                tbAgentEnterApplyPo.setUserId(userId);
                tbAgentEnterApplyPo.setSettleCode(code);
                tbAgentEnterApplyPo.setApplyNo(NoUtils.getAgentEnterApplyNo());
                tbAgentEnterApplyPo.setOpenid(tbAppUserPo.getOpenid());
                tbAgentEnterApplyPo.setPersonName(businessAgentBindDto.getPersonName());
                tbAgentEnterApplyPo.setCertType(CertTypeEnum.SFZ.getValue());
                tbAgentEnterApplyPo.setCertNo(businessAgentBindDto.getCertNo());
                tbAgentEnterApplyPo.setCertValidityType(businessAgentBindDto.getCertValidityType());
                tbAgentEnterApplyPo.setCertBeginDate(businessAgentBindDto.getCertBeginDate());
                tbAgentEnterApplyPo.setCertEndDate(businessAgentBindDto.getCertEndDate());
                tbAgentEnterApplyPo.setMobileNo(tbAppUserPo.getMobile());
                tbAgentEnterApplyPo.setHfId(tbAppUserPo.getHfId());
                tbAgentEnterApplyPo.setState(AgentEnterStateEnum.WAIT_ENTER.getValue());
                tbAgentEnterApplyPo.setApplyIp(businessAgentBindDto.getRequestIp());
                tbAgentEnterApplyPo.setApplyTime(now);
                tbAgentEnterApplyPo.setCreateTime(now);
                tbAgentEnterApplyPo.setUpdateTime(now);
                insert = baseMapper.insert(tbAgentEnterApplyPo);
                if (insert == 0) {
                    log.error("经纪人绑定商家失败,添加经纪人入驻记录失败,userId:{}, businessId:{}", userId, id);
                    Throw.isBusinessException("受邀失败");
                }

                if (firstEnter) {
                    tbAppUserPo.setEnterTime(now);
                }
            }

            // 是否是经纪人(1-不是，2-是)
            tbAppUserPo.setAgentState(AgentStateEnum.OPEN.getValue());
            tbAppUserPo.setUpdateTime(now);
            int update = appUserMapper.updateById(tbAppUserPo);
            if (update == 0) {
                log.error("经纪人绑定商家失败,更新经纪人状态失败,userId:{}, businessId:{}", userId, id);
                Throw.isBusinessException("受邀失败");
            }

            // 添加商家经纪人绑定记录
            TbBusinessAgentBindRecordPo tbBusinessAgentBindRecordPo = new TbBusinessAgentBindRecordPo();
            tbBusinessAgentBindRecordPo.setUserId(userId);
            tbBusinessAgentBindRecordPo.setBusinessId(id);
            tbBusinessAgentBindRecordPo.setBindTime(now);
            tbBusinessAgentBindRecordPo.setCreateTime(now);
            int insert = businessAgentBindRecordMapper.insert(tbBusinessAgentBindRecordPo);
            if (insert <= 0) {
                log.error("经纪人绑定商家失败,添加商家经纪人绑定记录失败,userId:{}, businessId:{}", userId, id);
                Throw.isBusinessException("受邀失败");
            }

            // 写入用户-商家关联表
            Boolean res = userBusinessService.related(userId, id);
            if (!res) {
                log.error("经纪人绑定商家失败,添加用户-商家关联表失败,userId:{}, businessId:{}", userId, id);
                Throw.isBusinessException("受邀失败");
            }

            transactionManager.commit(transaction);
        } catch (Exception e) {
            //回滚事务
            transactionManager.rollback(transaction);
            log.error("<经纪人绑定商家>事务异常回滚", e);
            Throw.isBusinessException("受邀失败");
        }

        // 将最新的用户数据缓存Redis
        String userInfoRedis = redisUtil.get(String.format(RedisKeyConstant.USER_INFO_KEY, userId));
        if (!StringUtils.isNullOrEmpty(userInfoRedis)) {
            UserInfo userInfo = JSON.parseObject(userInfoRedis, UserInfo.class);
            // 是否是经纪人(1-不是，2-是)
            userInfo.setAgentState(2);

            redisUtil.set(String.format(RedisKeyConstant.USER_INFO_KEY, userId), JSON.toJSONString(userInfo), Constant.USER_LOGIN_TIMEOUT, TimeUnit.SECONDS);
        }

        return true;
    }

    @Override
    public AgentEnterApplyVo bindHf(AgentBindHfDto agentBindHfDto) {
        Long userId = agentBindHfDto.getUserId();

        String personName = agentBindHfDto.getPersonName();
        if (StringUtils.isBlank(personName)) {
            Throw.isBusinessException("请输入姓名");
        }

        String certNo = agentBindHfDto.getCertNo();
        if (StringUtils.isBlank(certNo)) {
            Throw.isBusinessException("请输入身份证号");
        }

        Integer certValidityType = agentBindHfDto.getCertValidityType();
        if (certValidityType == null || CertValidityTypeEnum.typeOfValue(certValidityType) == null) {
            Throw.isBusinessException("请选择证件有效期");
        }

        String certBeginDate = agentBindHfDto.getCertBeginDate();
        if (CertValidityTypeEnum.NO.getValue().equals(certValidityType)) {
            String certEndDate = agentBindHfDto.getCertEndDate();
            if (StringUtils.isBlank(certBeginDate)) {
                Throw.isBusinessException("请选择证件有效期开始日期");
            }

            if (StringUtils.isBlank(certEndDate)) {
                Throw.isBusinessException("请选择证件有效期截止日期");
            }

            LocalDate legalCertBeginLocalDate = null;
            LocalDate legalCertEndLocalDate = null;
            try {
                legalCertBeginLocalDate = LocalDateUtil.toLocalDate(certBeginDate, Constant.YYYY_MM_DD);
            } catch (Exception e) {
                Throw.isBusinessException("证件有效期开始日期选择错误");
            }

            try {
                legalCertEndLocalDate = LocalDateUtil.toLocalDate(certEndDate, Constant.YYYY_MM_DD);
            } catch (Exception e) {
                Throw.isBusinessException("证件有效期截止日期选择错误");
            }

            if (legalCertEndLocalDate.compareTo(legalCertBeginLocalDate) <= 0) {
                Throw.isBusinessException("证件有效期截止日期必须大于开始日期");
            }
        } else {
            // 如果是长期有效，法人证件有效期开始日期也不能为空
            if (StringUtils.isBlank(certBeginDate)) {
                Throw.isBusinessException("请选择证件有效期开始日期");
            }

            LocalDate legalCertBeginLocalDate = null;
            try {
                legalCertBeginLocalDate = LocalDateUtil.toLocalDate(certBeginDate, Constant.YYYY_MM_DD);
            } catch (Exception e) {
                Throw.isBusinessException("证件有效期开始日期选择错误");
            }
        }

        TbAppUserPo tbAppUserPo = appUserMapper.selectById(userId);
        if (tbAppUserPo == null || tbAppUserPo.getDelState() != 0) {
            Throw.isBusinessException("未找到用户数据");
        }
        String hfId = tbAppUserPo.getHfId();

        AgentEnterApplyDto agentEnterApplyDto = new AgentEnterApplyDto();
        agentEnterApplyDto.setUserId(userId);
        agentEnterApplyDto.setApplyIp(agentBindHfDto.getRequestIp());
        agentEnterApplyDto.setCardName(agentBindHfDto.getCardName());
        agentEnterApplyDto.setCardNo(agentBindHfDto.getCardNo());
        agentEnterApplyDto.setBankProvinceCode(agentBindHfDto.getBankProvinceCode());
        agentEnterApplyDto.setBankProvinceName(agentBindHfDto.getBankProvinceName());
        agentEnterApplyDto.setBankCityCode(agentBindHfDto.getBankCityCode());
        agentEnterApplyDto.setBankCityName(agentBindHfDto.getBankCityName());

        if (!StringUtils.isBlank(hfId)) {
            return enterApply(agentEnterApplyDto);
        }

        // 调用汇付个人用户基本信息开户接口
        HfAgentUserEnterApply hfAgentUserEnterApply = new HfAgentUserEnterApply();
        hfAgentUserEnterApply.setPersonName(agentBindHfDto.getPersonName());
        hfAgentUserEnterApply.setCertNo(agentBindHfDto.getCertNo());
        hfAgentUserEnterApply.setCertValidityType(agentBindHfDto.getCertValidityType());
        hfAgentUserEnterApply.setCertBeginDate(agentBindHfDto.getCertBeginDate());
        hfAgentUserEnterApply.setCertEndDate(agentBindHfDto.getCertEndDate());
        hfAgentUserEnterApply.setMobileNo(tbAppUserPo.getMobile());
        JSONObject jsonObject = hfApi.agentUserInvite(hfAgentUserEnterApply).unpack();
        if (jsonObject == null) {
            log.error("经纪人入驻汇付失败:{}", hfAgentUserEnterApply);
            Throw.isBusinessException("绑定失败，请联系客服");
        }

        JSONObject dataJSONObject = jsonObject.getJSONObject("data");
        String respCode = dataJSONObject.getString("resp_code");
        String respDesc = dataJSONObject.getString("resp_desc");
        if (!"00000000".equals(respCode) && !"00000100".equals(respCode) && !"00000102".equals(respCode) && !"90000000".equals(respCode)) {
            Throw.isBusinessException(respDesc);
        }

        LocalDateTime now = LocalDateTime.now();

        hfId = dataJSONObject.getString("huifu_id");
        if (!StringUtils.isBlank(hfId)) {
            tbAppUserPo.setHfId(hfId);
        }
        tbAppUserPo.setRealName(agentBindHfDto.getPersonName());
        tbAppUserPo.setCertNo(agentBindHfDto.getCertNo());
        tbAppUserPo.setCertValidityType(agentBindHfDto.getCertValidityType());
        tbAppUserPo.setCertBeginDate(agentBindHfDto.getCertBeginDate());
        tbAppUserPo.setCertEndDate(agentBindHfDto.getCertEndDate());

        TransactionStatus transaction = transactionManager.getTransaction(new DefaultTransactionAttribute());

        try {
            // 添加经纪人入驻记录
            TbAgentEnterApplyPo tbAgentEnterApplyPo = new TbAgentEnterApplyPo();
            tbAgentEnterApplyPo.setUserId(userId);
            tbAgentEnterApplyPo.setSettleCode("");
            tbAgentEnterApplyPo.setApplyNo(NoUtils.getAgentEnterApplyNo());
            tbAgentEnterApplyPo.setOpenid(tbAppUserPo.getOpenid());
            tbAgentEnterApplyPo.setPersonName(agentBindHfDto.getPersonName());
            tbAgentEnterApplyPo.setCertType(CertTypeEnum.SFZ.getValue());
            tbAgentEnterApplyPo.setCertNo(agentBindHfDto.getCertNo());
            tbAgentEnterApplyPo.setCertValidityType(agentBindHfDto.getCertValidityType());
            tbAgentEnterApplyPo.setCertBeginDate(agentBindHfDto.getCertBeginDate());
            tbAgentEnterApplyPo.setCertEndDate(agentBindHfDto.getCertEndDate());
            tbAgentEnterApplyPo.setMobileNo(tbAppUserPo.getMobile());
            tbAgentEnterApplyPo.setHfId(tbAppUserPo.getHfId());
            tbAgentEnterApplyPo.setState(AgentEnterStateEnum.WAIT_ENTER.getValue());
            tbAgentEnterApplyPo.setApplyIp(agentBindHfDto.getRequestIp());
            tbAgentEnterApplyPo.setApplyTime(now);
            tbAgentEnterApplyPo.setCreateTime(now);
            tbAgentEnterApplyPo.setUpdateTime(now);
            int insert = baseMapper.insert(tbAgentEnterApplyPo);
            if (insert == 0) {
                log.error("入驻汇付失败,添加经纪人入驻记录失败,tbAgentEnterApplyPo:{}", tbAgentEnterApplyPo);
                Throw.isBusinessException("入驻失败");
            }

            tbAppUserPo.setUpdateTime(now);
            int update = appUserMapper.updateById(tbAppUserPo);
            if (update == 0) {
                log.error("入驻汇付失败,更新经纪人状态失败,tbAppUserPo:{}", tbAppUserPo);
                Throw.isBusinessException("入驻失败");
            }

            transactionManager.commit(transaction);
        } catch (Exception e) {
            //回滚事务
            transactionManager.rollback(transaction);
            log.error("<入驻汇付失败>事务异常回滚", e);
            Throw.isBusinessException("入驻汇付失败");
        }

        return enterApply(agentEnterApplyDto);
    }

    @Override
    public List<AgentBankCardVo> listBank(Long userId) {
        List<AgentBankCardVo> agentBankCardVos = new ArrayList<>();

        // 查询是否存在修改成功的经纪人银行卡记录，倒序取第一条
        List<TbAgentBankUpdateRecordPo> tbAgentBankUpdateRecordPos = agentBankUpdateRecordMapper.selectList(new QueryWrapper<TbAgentBankUpdateRecordPo>()
                .eq("del_state", 0)
                .eq("user_id", userId)
                .eq("audit_state", AuditStateEnum.SUCCESS.getValue())
                .orderByDesc("apply_time"));
        if (!CollectionUtils.isEmpty(tbAgentBankUpdateRecordPos)) {
            TbAgentBankUpdateRecordPo tbAgentBankUpdateRecordPo = tbAgentBankUpdateRecordPos.get(0);
            AgentBankCardVo agentBankCardVo = new AgentBankCardVo();
            agentBankCardVo.setCardName(PrivacyUtil.encryptRealName(tbAgentBankUpdateRecordPo.getCardName()));
            agentBankCardVo.setCardNo(PrivacyUtil.encryptBankAccount(tbAgentBankUpdateRecordPo.getCardNo()));

            agentBankCardVos.add(agentBankCardVo);
            return agentBankCardVos;
        }

        List<TbAgentEnterApplyPo> tbAgentEnterApplyPos = baseMapper.selectList(new QueryWrapper<TbAgentEnterApplyPo>()
                .eq("del_state", 0)
                .eq("user_id", userId)
                .eq("state", AgentEnterStateEnum.SIGN_SUCCESS.getValue())
                .orderByDesc("apply_time"));
        if (!CollectionUtils.isEmpty(tbAgentEnterApplyPos)) {
            TbAgentEnterApplyPo tbAgentEnterApplyPo = tbAgentEnterApplyPos.get(0);
            AgentBankCardVo agentBankCardVo = new AgentBankCardVo();
            agentBankCardVo.setCardName(PrivacyUtil.encryptRealName(tbAgentEnterApplyPo.getCardName()));
            agentBankCardVo.setCardNo(PrivacyUtil.encryptBankAccount(tbAgentEnterApplyPo.getCardNo()));

            agentBankCardVos.add(agentBankCardVo);
            return agentBankCardVos;
        }

        return null;
    }

    @Override
    public AgentEnterApplyVo enterApply(AgentEnterApplyDto agentEnterApplyDto) {
        String cardName = agentEnterApplyDto.getCardName();
        String cardNo = agentEnterApplyDto.getCardNo();
        String bankProvinceCode = agentEnterApplyDto.getBankProvinceCode();
        String bankProvinceName = agentEnterApplyDto.getBankProvinceName();
        String bankCityCode = agentEnterApplyDto.getBankCityCode();
        String bankCityName = agentEnterApplyDto.getBankCityName();

        // 校验参数
        if (StringUtils.isBlank(cardName)) {
            Throw.isBusinessException("请输入持卡人姓名");
        }

        if (StringUtils.isBlank(cardNo)) {
            Throw.isBusinessException("请输入银行卡号");
        }

        if (StringUtils.isBlank(bankProvinceCode) || StringUtils.isBlank(bankProvinceName)) {
            Throw.isBusinessException("请选择银行所在省份");
        }

        if (StringUtils.isBlank(bankCityCode) || StringUtils.isBlank(bankCityName)) {
            Throw.isBusinessException("请选择银行所在城市");
        }

        List<TbAgentEnterApplyPo> tbAgentEnterApplyPos = baseMapper.selectList(new QueryWrapper<TbAgentEnterApplyPo>().eq("del_state", 0)
                .eq("user_id", agentEnterApplyDto.getUserId()).orderByDesc("apply_time"));
        if (CollectionUtils.isEmpty(tbAgentEnterApplyPos)) {
            Throw.isBusinessException("请先开户");
        }

        TbAgentEnterApplyPo tbAgentEnterApplyPo = tbAgentEnterApplyPos.get(0);
        Integer state = tbAgentEnterApplyPo.getState();
        String hfId = tbAgentEnterApplyPo.getHfId();

        tbAgentEnterApplyPo.setCardName(cardName);
        tbAgentEnterApplyPo.setCardNo(cardNo);
        tbAgentEnterApplyPo.setBankProvinceCode(bankProvinceCode);
        tbAgentEnterApplyPo.setBankProvinceName(bankProvinceName);
        tbAgentEnterApplyPo.setBankCityCode(bankCityCode);
        tbAgentEnterApplyPo.setBankCityName(bankCityName);

        // 如果是待入驻/入驻失败，调用汇付用户业务入驻接口，修改入驻状态=入驻审核中
        if (AgentEnterStateEnum.WAIT_ENTER.getValue().equals(state)
                || AgentEnterStateEnum.ENTER_FAIL.getValue().equals(state)) {
            TbAppUserPo tbAppUserPo = appUserMapper.selectById(agentEnterApplyDto.getUserId());

            LocalDateTime nowLocalDateTime = LocalDateUtil.getNowLocalDateTime();
            String yyyyMMddHHmmss = LocalDateUtil.toLocalDateTimeToString(nowLocalDateTime, "yyyyMMddHHmmss");
            String yyyyMMdd = LocalDateUtil.toLocalDateToString(nowLocalDateTime.toLocalDate(), "yyyyMMdd");
            String busiReqSeqId = yyyyMMddHHmmss + GenerateUtil.getRandomNum(5);

            // 调用汇付用户业务入驻接口
            HfAgentUserEnterApply hfAgentUserEnterApply = new HfAgentUserEnterApply();
            hfAgentUserEnterApply.setReqSeqId(busiReqSeqId);
            hfAgentUserEnterApply.setReqDate(yyyyMMdd);
            hfAgentUserEnterApply.setHfId(hfId);
            hfAgentUserEnterApply.setCardName(cardName);
            hfAgentUserEnterApply.setCardNo(cardNo);
            hfAgentUserEnterApply.setCertNo(tbAppUserPo.getCertNo());
            hfAgentUserEnterApply.setCertValidityType(tbAppUserPo.getCertValidityType());
            hfAgentUserEnterApply.setCertBeginDate(tbAppUserPo.getCertBeginDate());
            hfAgentUserEnterApply.setCertEndDate(tbAppUserPo.getCertEndDate());
            hfAgentUserEnterApply.setMobileNo(tbAppUserPo.getMobile());
            hfAgentUserEnterApply.setBankProvinceCode(bankProvinceCode);
            hfAgentUserEnterApply.setBankCityCode(bankCityCode);
            JSONObject jsonObject = hfApi.agentUserOpen(hfAgentUserEnterApply).unpack();
            if (jsonObject != null) {
                JSONObject dataJSONObject = jsonObject.getJSONObject("data");
                String respCode = dataJSONObject.getString("resp_code");
                // 取现卡序列号
                String tokenNo = dataJSONObject.getString("token_no");
                if (!StringUtils.isBlank(tokenNo)) {
                    tbAgentEnterApplyPo.setTokenNo(tokenNo);
                    baseMapper.updateById(tbAgentEnterApplyPo);
                }
                if (!"00000000".equals(respCode)) {
                    // 个人用户已开通汇优财, 或存在处理中的开通申请
                    String respDesc = dataJSONObject.getString("resp_desc");
                    AgentEnterApplyVo agentEnterApplyVo = new AgentEnterApplyVo();
                    agentEnterApplyVo.setState(AgentEnterStateEnum.ENTER_FAIL.getValue());
                    agentEnterApplyVo.setRefuseReason(respDesc);
                    return agentEnterApplyVo;
                } else {
                    boolean businessFlag = false;
                    JSONArray respBusinessJSONArray = dataJSONObject.getJSONArray("resp_business");
                    if (respBusinessJSONArray != null && respBusinessJSONArray.size() > 0) {
                        for (int i = 0; i < respBusinessJSONArray.size(); i++) {
                            JSONObject respBusinessJSONObject = respBusinessJSONArray.getJSONObject(i);
                            // 配置类型	1、绑卡信息；2、取现配置；3、结算信息配置；
                            String type = respBusinessJSONObject.getString("type");
                            // 配置返回信息	业务响应信息；
                            String msg = respBusinessJSONObject.getString("msg");
                            // 配置状态	S:成功，F:失败；
                            String code = respBusinessJSONObject.getString("code");
                            if (!"S".equals(code)) {
                                businessFlag = true;
                                break;
                            }
                        }
                    }

                    if (businessFlag) {
                        log.error("业务配置结果失败, respBusinessJSONArray:{}", JSON.toJSONString(dataJSONObject));
                        Throw.isBusinessException("入驻失败，请联系客服");
                    }
                }
            }

            tbAgentEnterApplyPo.setState(AgentEnterStateEnum.ENTER_AUDIT.getValue());
            // 更新经纪人入驻记录
            tbAgentEnterApplyPo.setBusiReqDate(yyyyMMdd);
            tbAgentEnterApplyPo.setBusiReqSeqId(busiReqSeqId);
            tbAgentEnterApplyPo.setUpdateTime(nowLocalDateTime);
            baseMapper.updateById(tbAgentEnterApplyPo);

            AgentEnterApplyVo agentEnterApplyVo = new AgentEnterApplyVo();
            agentEnterApplyVo.setState(tbAgentEnterApplyPo.getState());
            if (AgentEnterStateEnum.WAIT_SIGN.getValue().equals(tbAgentEnterApplyPo.getState())
                    || AgentEnterStateEnum.ENTER_AUDIT.getValue().equals(tbAgentEnterApplyPo.getState())) {
                agentEnterApplyVo.setSignUrl(PrivacyUtil.encryptMobile(tbAgentEnterApplyPo.getMobileNo()));
            }
            return agentEnterApplyVo;
        }

        // 如果是签约失败，调用个人签约发起接口去签约，修改入驻状态=待签约
        if (AgentEnterStateEnum.SIGN_FAIL.getValue().equals(state)) {
            // 调用汇付个人签约发起接口
            LocalDateTime nowLocalDateTime = LocalDateUtil.getNowLocalDateTime();
            String yyyyMMddHHmmss = LocalDateUtil.toLocalDateTimeToString(nowLocalDateTime, "yyyyMMddHHmmss");
            String yyyyMMdd = LocalDateUtil.toLocalDateToString(nowLocalDateTime.toLocalDate(), "yyyyMMdd");
            String signReqSeqId = yyyyMMddHHmmss + GenerateUtil.getRandomNum(5);

            HfAgentUserSignCreate hfAgentUserSignCreate = new HfAgentUserSignCreate();
            hfAgentUserSignCreate.setHfId(hfId);
            hfAgentUserSignCreate.setMinorAgentId(HfConstant.MINOR_AGENT_ID);
            hfAgentUserSignCreate.setReqSeqId(signReqSeqId);
            hfAgentUserSignCreate.setReqDate(yyyyMMdd);
            // 调用个人签约发起接口去签约
            JSONObject agentSignCreateJSONObject = hfApi.agentSignCreate(hfAgentUserSignCreate).unpack();
            if (agentSignCreateJSONObject == null) {
                log.error("经纪人入驻失败，调用个人签约发起接口去签约失败,hfAgentUserSignCreate:{}", JSON.toJSONString(hfAgentUserSignCreate));
                Throw.isBusinessException("签约失败，请联系客服");
            }
            log.info("个人签约发起result:{}", JSON.toJSONString(agentSignCreateJSONObject));

            JSONObject signDataJSONObject = agentSignCreateJSONObject.getJSONObject("data");
            String agentSignCreateRespCode = signDataJSONObject.getString("resp_code");
            if (!"00000000".equals(agentSignCreateRespCode)) {
                log.error("经纪人入驻失败，个人签约发起返回错误，{}", JSON.toJSONString(agentSignCreateJSONObject));
                Throw.isBusinessException("签约失败，请联系客服");
            }
            String contractId = signDataJSONObject.getString("contract_id");
            String contractName = signDataJSONObject.getString("contract_name");

            // 签约状态	0-未签约 1-已签约；
            Integer signState = signDataJSONObject.getInteger("sign_state");
            if (signState == 1) {
                // 状态(1-待入驻，2-入驻失败，3-待签约，4-签约成功，5-签约失败)
                tbAgentEnterApplyPo.setState(AgentEnterStateEnum.SIGN_SUCCESS.getValue());
                // 更新该经纪人下绑定的商家的状态为已签约
                businessAgentMapper.updateStateByUserId(tbAgentEnterApplyPo.getUserId(), AgentEnterStateEnum.SIGN_SUCCESS.getValue());
            } else {
                // 签约地址
                String signUrl = signDataJSONObject.getString("sign_url");
                tbAgentEnterApplyPo.setSignUrl(signUrl);
                tbAgentEnterApplyPo.setState(AgentEnterStateEnum.WAIT_SIGN.getValue());
                tbAgentEnterApplyPo.setEnterTime(LocalDateTime.now());
            }

            tbAgentEnterApplyPo.setSignReqDate(yyyyMMdd);
            tbAgentEnterApplyPo.setSignReqSeqId(signReqSeqId);
            tbAgentEnterApplyPo.setMinorAgentId(HfConstant.MINOR_AGENT_ID);
            tbAgentEnterApplyPo.setMinorMemberId(HfConstant.MINOR_MEMBER_ID);
            tbAgentEnterApplyPo.setCompanyName(HfConstant.COMPANY_NAME);
            tbAgentEnterApplyPo.setContractName(contractName);
            tbAgentEnterApplyPo.setContractId(contractId);
            tbAgentEnterApplyPo.setUpdateTime(nowLocalDateTime);
            baseMapper.updateById(tbAgentEnterApplyPo);

            AgentEnterApplyVo agentEnterApplyVo = new AgentEnterApplyVo();
            agentEnterApplyVo.setState(tbAgentEnterApplyPo.getState());
            if (AgentEnterStateEnum.WAIT_SIGN.getValue().equals(tbAgentEnterApplyPo.getState())
                    || AgentEnterStateEnum.ENTER_AUDIT.getValue().equals(tbAgentEnterApplyPo.getState())) {
                agentEnterApplyVo.setSignUrl(PrivacyUtil.encryptMobile(tbAgentEnterApplyPo.getMobileNo()));
            }
            return agentEnterApplyVo;
        }

        // 否则返回对应的状态给前端做跳转
        AgentEnterApplyVo agentEnterApplyVo = new AgentEnterApplyVo();
        agentEnterApplyVo.setState(tbAgentEnterApplyPo.getState());
        if (AgentEnterStateEnum.WAIT_SIGN.getValue().equals(tbAgentEnterApplyPo.getState())
                || AgentEnterStateEnum.ENTER_AUDIT.getValue().equals(tbAgentEnterApplyPo.getState())) {
            agentEnterApplyVo.setSignUrl(PrivacyUtil.encryptMobile(tbAgentEnterApplyPo.getMobileNo()));
        }
        return agentEnterApplyVo;
    }

    @Override
    public AgentEnterApplyStateVo getEnterInfoState(Long userId) {
        AgentEnterApplyStateVo agentEnterApplyStateVo = new AgentEnterApplyStateVo();

        List<TbAgentEnterApplyPo> tbAgentEnterApplyPos = baseMapper.selectList(new QueryWrapper<TbAgentEnterApplyPo>().eq("del_state", 0)
                .eq("user_id", userId).orderByDesc("apply_time"));
        if (CollectionUtils.isEmpty(tbAgentEnterApplyPos)) {
            agentEnterApplyStateVo.setState(1);
            return agentEnterApplyStateVo;
        }

        TbAgentEnterApplyPo tbAgentEnterApplyPo = tbAgentEnterApplyPos.get(0);

        Integer state = tbAgentEnterApplyPo.getState();
        if (AgentEnterStateEnum.WAIT_SIGN.getValue().equals(state)) {
            // 调用hf个人签约状态查询接口
            JSONObject jsonObject = hfApi.agentSignQuery(tbAgentEnterApplyPo.getContractId()).unpack();
            if (jsonObject != null) {
                JSONObject data = jsonObject.getJSONObject("data");
                // 签约状态	0-未签约 1-已签约 2:签约中；
                String signState = data.getString("sign_state");
                if ("1".equals(signState)) {
                    tbAgentEnterApplyPo.setState(AgentEnterStateEnum.SIGN_SUCCESS.getValue());

                    // 更新该经纪人下绑定的商家的状态为已签约
                    businessAgentMapper.updateStateByUserId(tbAgentEnterApplyPo.getUserId(), AgentEnterStateEnum.SIGN_SUCCESS.getValue());
                } else {
                    tbAgentEnterApplyPo.setState(AgentEnterStateEnum.WAIT_SIGN.getValue());
                    tbAgentEnterApplyPo.setSignUrl(tbAgentEnterApplyPo.getSignUrl());
                }
            }
        }

        agentEnterApplyStateVo.setState(tbAgentEnterApplyPo.getState());
        if (AgentEnterStateEnum.ENTER_FAIL.getValue().equals(tbAgentEnterApplyPo.getState())
                || AgentEnterStateEnum.SIGN_FAIL.getValue().equals(tbAgentEnterApplyPo.getState())) {
            agentEnterApplyStateVo.setRefuseReason(tbAgentEnterApplyPo.getRefuseReason());
        }

        if (AgentEnterStateEnum.WAIT_SIGN.getValue().equals(tbAgentEnterApplyPo.getState())
                || AgentEnterStateEnum.ENTER_AUDIT.getValue().equals(tbAgentEnterApplyPo.getState())) {
            agentEnterApplyStateVo.setSignUrl(PrivacyUtil.encryptMobile(tbAgentEnterApplyPo.getMobileNo()));
        }

        return agentEnterApplyStateVo;
    }

    @Override
    public Boolean agentUserEntAuditCallback(JSONObject dataObj) {
        // H:灵活用工 A:审核消息
        String notifyType = dataObj.getString("notify_type");
        if (!"H".equals(notifyType)) {
            log.error("用户业务入驻异步通知回调失败，不是灵活用工用户业务入驻异步通知回调，data：{}", JSON.toJSONString(dataObj));
            return false;
        }

        String hfId = dataObj.getString("huifu_id");
        String reqDate = dataObj.getString("req_date");
        String reqSeqId = dataObj.getString("req_seq_id");
        // 灵活用工场景下，1-待开户，2-开户成功待签约，3-开户失败，4-签约成功，5-签约失败；
        String state = dataObj.getString("state");
        String stateDesc = dataObj.getString("state_desc");

        List<TbAgentEnterApplyPo> tbAgentEnterApplyPos = baseMapper.selectList(new QueryWrapper<TbAgentEnterApplyPo>().eq("del_state", 0)
                .eq("busi_req_seq_id", reqSeqId)
                .eq("busi_req_date", reqDate)
                .eq("state", AgentEnterStateEnum.ENTER_AUDIT.getValue())
                .orderByDesc("apply_time"));
        if (CollectionUtils.isEmpty(tbAgentEnterApplyPos)) {
            log.error("用户业务入驻异步通知回调失败，未找到入驻审核中的记录，data：{}", JSON.toJSONString(dataObj));
            return false;
        }

        TbAgentEnterApplyPo tbAgentEnterApplyPo = tbAgentEnterApplyPos.get(0);
        Long userId = tbAgentEnterApplyPo.getUserId();

        if ("2".equals(state)) {
            // 开户成功待签约，做签约操作
            // 调用汇付个人签约发起接口
            LocalDateTime nowLocalDateTime = LocalDateUtil.getNowLocalDateTime();
            String yyyyMMddHHmmss = LocalDateUtil.toLocalDateTimeToString(nowLocalDateTime, "yyyyMMddHHmmss");
            String yyyyMMdd = LocalDateUtil.toLocalDateToString(nowLocalDateTime.toLocalDate(), "yyyyMMdd");
            String signReqSeqId = yyyyMMddHHmmss + GenerateUtil.getRandomNum(5);

            HfAgentUserSignCreate hfAgentUserSignCreate = new HfAgentUserSignCreate();
            hfAgentUserSignCreate.setHfId(hfId);
            hfAgentUserSignCreate.setMinorAgentId(HfConstant.MINOR_AGENT_ID);
            hfAgentUserSignCreate.setReqSeqId(signReqSeqId);
            hfAgentUserSignCreate.setReqDate(yyyyMMdd);
            // 调用个人签约发起接口去签约
            JSONObject agentSignCreateJSONObject = hfApi.agentSignCreate(hfAgentUserSignCreate).unpack();
            if (agentSignCreateJSONObject == null) {
                log.error("用户业务入驻异步通知回调失败，调用个人签约发起接口去签约失败,hfAgentUserSignCreate:{}", JSON.toJSONString(hfAgentUserSignCreate));
                return false;
            }
            log.info("个人签约发起result:{}", JSON.toJSONString(agentSignCreateJSONObject));

            JSONObject signDataJSONObject = agentSignCreateJSONObject.getJSONObject("data");
            String agentSignCreateRespCode = signDataJSONObject.getString("resp_code");
            if (!"00000000".equals(agentSignCreateRespCode)) {
                log.error("用户业务入驻异步通知回调失败，个人签约发起返回错误，{}", JSON.toJSONString(agentSignCreateJSONObject));
                return false;
            }
            String contractId = signDataJSONObject.getString("contract_id");
            String contractName = signDataJSONObject.getString("contract_name");

            // 签约状态	0-未签约 1-已签约；
            Integer signState = signDataJSONObject.getInteger("sign_state");
            if (signState == 1) {
                // 状态(1-待入驻，2-入驻失败，3-待签约，4-签约成功，5-签约失败)
                tbAgentEnterApplyPo.setState(AgentEnterStateEnum.SIGN_SUCCESS.getValue());
                // 更新该经纪人下绑定的商家的状态为已签约
                businessAgentMapper.updateStateByUserId(userId, AgentEnterStateEnum.SIGN_SUCCESS.getValue());
            } else {
                // 签约地址
                String signUrl = signDataJSONObject.getString("sign_url");
                tbAgentEnterApplyPo.setSignUrl(signUrl);
                tbAgentEnterApplyPo.setState(AgentEnterStateEnum.WAIT_SIGN.getValue());
                tbAgentEnterApplyPo.setEnterTime(LocalDateTime.now());
            }

            tbAgentEnterApplyPo.setSignReqDate(yyyyMMdd);
            tbAgentEnterApplyPo.setSignReqSeqId(signReqSeqId);
            tbAgentEnterApplyPo.setMinorAgentId(HfConstant.MINOR_AGENT_ID);
            tbAgentEnterApplyPo.setMinorMemberId(HfConstant.MINOR_MEMBER_ID);
            tbAgentEnterApplyPo.setCompanyName(HfConstant.COMPANY_NAME);
            tbAgentEnterApplyPo.setContractName(contractName);
            tbAgentEnterApplyPo.setContractId(contractId);
            tbAgentEnterApplyPo.setUpdateTime(nowLocalDateTime);
            int update = baseMapper.updateById(tbAgentEnterApplyPo);
            if (update == 0) {
                log.error("用户业务入驻异步通知回调失败，更新经纪人入驻申请状态失败,agentEnterApplyId:{}", tbAgentEnterApplyPo.getId());
            }
        } else if ("3".equals(state)) {
            // 开户失败，记录失败原因，更新状态
            tbAgentEnterApplyPo.setState(AgentEnterStateEnum.ENTER_FAIL.getValue());
            tbAgentEnterApplyPo.setRefuseReason(stateDesc);
            tbAgentEnterApplyPo.setHfFailReason(JSON.toJSONString(dataObj));
            tbAgentEnterApplyPo.setUpdateTime(LocalDateTime.now());
            int update = baseMapper.updateById(tbAgentEnterApplyPo);
            if (update == 0) {
                log.error("用户业务入驻异步通知回调失败，更新经纪人入驻申请状态失败，agentEnterApplyId:{}", tbAgentEnterApplyPo.getId());
            }
        } else if ("4".equals(state)) {
            // 签约成功
            tbAgentEnterApplyPo.setState(AgentEnterStateEnum.SIGN_SUCCESS.getValue());
            tbAgentEnterApplyPo.setUpdateTime(LocalDateTime.now());
            int update = baseMapper.updateById(tbAgentEnterApplyPo);
            if (update == 0) {
                log.error("用户业务入驻异步通知回调失败，更新经纪人入驻申请状态失败，agentEnterApplyId:{}", tbAgentEnterApplyPo.getId());
            }
        } else if ("5".equals(state)) {
            // 签约失败，记录失败原因，更新状态
            tbAgentEnterApplyPo.setState(AgentEnterStateEnum.SIGN_FAIL.getValue());
            tbAgentEnterApplyPo.setRefuseReason(stateDesc);
            tbAgentEnterApplyPo.setHfFailReason(JSON.toJSONString(dataObj));
            tbAgentEnterApplyPo.setUpdateTime(LocalDateTime.now());
            int update = baseMapper.updateById(tbAgentEnterApplyPo);
            if (update == 0) {
                log.error("用户业务入驻异步通知回调失败，更新经纪人入驻申请状态失败，agentEnterApplyId:{}", tbAgentEnterApplyPo.getId());
            }
        }

        return true;
    }

    @Override
    public Boolean agentUserSignCallback(JSONObject dataObj) {
        // 合同编号
        String contractId = dataObj.getString("contract_id");
        // 状态   1:签约成功，0:签约失败；
        String state = dataObj.getString("state");

        List<TbAgentEnterApplyPo> tbAgentEnterApplyPos = baseMapper.selectList(new QueryWrapper<TbAgentEnterApplyPo>().eq("del_state", 0)
                .eq("contract_id", contractId).orderByDesc("apply_time"));
        if (CollectionUtils.isEmpty(tbAgentEnterApplyPos)) {
            log.error("用户签约结果异步通知回调失败，未找到签约数据，dataObj:{}", JSON.toJSONString(dataObj));
            return false;
        }

        TbAgentEnterApplyPo tbAgentEnterApplyPo = tbAgentEnterApplyPos.get(0);

        if ("1".equals(state)) {
            // 更新入驻申请状态
            tbAgentEnterApplyPo.setState(AgentEnterStateEnum.SIGN_SUCCESS.getValue());
            tbAgentEnterApplyPo.setSignTime(LocalDateTime.now());
            int update = baseMapper.updateById(tbAgentEnterApplyPo);
            if (update == 0) {
                log.error("用户签约结果异步通知回调失败，更新经纪人入驻申请状态失败,agentEnterApplyId:{}", tbAgentEnterApplyPo.getId());
            }

            // 更新该经纪人下绑定的商家的状态为已签约
            Integer count = businessAgentMapper.updateStateByUserId(tbAgentEnterApplyPo.getUserId(), AgentEnterStateEnum.SIGN_SUCCESS.getValue());
            if (count == null || count <= 0) {
                log.error("用户签约结果异步通知回调失败，更新该经纪人下绑定的商家的状态为已签约失败,agentEnterApplyId:{}", tbAgentEnterApplyPo.getId());
            }
        } else {
            // 签约失败
            // 更新入驻申请状态
            tbAgentEnterApplyPo.setState(AgentEnterStateEnum.SIGN_FAIL.getValue());
            tbAgentEnterApplyPo.setRefuseReason("签约失败，请联系客服");
            tbAgentEnterApplyPo.setHfFailReason(JSON.toJSONString(dataObj));
            int update = baseMapper.updateById(tbAgentEnterApplyPo);
            if (update == 0) {
                log.error("用户签约结果异步通知回调失败，更新经纪人入驻申请状态失败,agentEnterApplyId:{}", tbAgentEnterApplyPo.getId());
            }
        }

        return true;
    }

    @Override
    public List<AgentEnterApplyDetailVo> listByDto(AgentEnterApplyDetailDto agentEnterApplyDetailDto) {
        return baseMapper.listByDto(agentEnterApplyDetailDto);
    }

    @Override
    public Boolean updateBankInfo(AgentUpdateBankInfoDto agentUpdateBankInfoDto) {
        String mobile = agentUpdateBankInfoDto.getMobile();
        String smsCode = agentUpdateBankInfoDto.getSmsCode();
        String cardName = agentUpdateBankInfoDto.getCardName();
        String cardNo = agentUpdateBankInfoDto.getCardNo();
        String bankProvinceCode = agentUpdateBankInfoDto.getBankProvinceCode();
        String bankProvinceName = agentUpdateBankInfoDto.getBankProvinceName();
        String bankCityCode = agentUpdateBankInfoDto.getBankCityCode();
        String bankCityName = agentUpdateBankInfoDto.getBankCityName();
        Long userId = agentUpdateBankInfoDto.getUserId();

        if (userId == null || userId <= 0) {
            Throw.isBusinessException(ResponseEnums.USER_ACCESS_DENIED);
        }

        if (StringUtils.isBlank(mobile)) {
            // 根据用户id查询用户数据
            TbAppUserPo tbAppUserPo = appUserMapper.selectById(userId);
            if (tbAppUserPo == null || tbAppUserPo.getDelState() != 0) {
                Throw.isBusinessException(ResponseEnums.USER_NOT_FOUND);
            }

            mobile = tbAppUserPo.getMobile();
        }

        // 校验信息
        if (StringUtils.isBlank(smsCode)) {
            Throw.isBusinessException("请输入短信验证码");
        }

        if (StringUtils.isBlank(cardName)) {
            Throw.isBusinessException("请输入账户名称");
        }

        if (StringUtils.isBlank(cardNo)) {
            Throw.isBusinessException("请输入银行卡号");
        }

        if (StringUtils.isBlank(bankProvinceCode) || StringUtils.isBlank(bankProvinceName)) {
            Throw.isBusinessException("请选择银行所在省份");
        }

        if (StringUtils.isBlank(bankCityCode) || StringUtils.isBlank(bankCityName)) {
            Throw.isBusinessException("请选择银行所在城市");
        }

        // 如果存在未完成（即非提现失败/提现成功/审核失败状态）的提现记录，则不能申请修改提现银行卡
        Integer count = withdrawalBillMapper.selectCount(new QueryWrapper<TbWithdrawalBillPo>().eq("del_state", 0)
                .eq("withdrawal_type", WithdrawalTypeEnum.AGENT_COMMISSION.getValue())
                .eq("withdrawal_user_id", userId)
                .notIn("state", Arrays.asList(WithdrawalStateEnum.WITHDRAWAL_SUCCESS.getValue(),
                        WithdrawalStateEnum.WITHDRAWAL_FAIL.getValue(),
                        WithdrawalStateEnum.AUDIT_FAIL.getValue())));
        if (count != null && count > 0) {
            log.error("经纪人更新银行卡失败，存在未完成的提现记录，userId：{}", userId);
            Throw.isBusinessException("存在未完成的提现记录，不能修改银行卡信息");
        }

        // 对手机号加锁
        String lockKey = MessageFormat.format(Constant.LOCK_FORMAT, "updateAgentBankInfo:" + mobile);
        try {
            LockUtils.blockLock(lockKey, Constant.AUTO_UNLOCK_SECOND);

            // 校验短信验证码
            SmsVerifyDto smsVerifyDto = new SmsVerifyDto();
            smsVerifyDto.setCode(smsCode);
            smsVerifyDto.setMobile(mobile);
            smsVerifyDto.setType(SmsTypeEnum.SMS_UPDATE_AGENT_BANK_INFO.getValue());
            smsBiz.verify(smsVerifyDto).isSuccess();

            // 查询经纪人入驻信息，判断是否有绑定银行卡并签约成功，并获取hfId
            List<TbAgentEnterApplyPo> tbAgentEnterApplyPos = baseMapper.selectList(new QueryWrapper<TbAgentEnterApplyPo>()
                    .eq("del_state", 0)
                    .eq("user_id", userId)
                    .orderByDesc("apply_time"));
            if (CollectionUtils.isEmpty(tbAgentEnterApplyPos)) {
                Throw.isBusinessException("请先开户");
            }

            TbAgentEnterApplyPo tbAgentEnterApplyPo = tbAgentEnterApplyPos.get(0);
            if (!AgentEnterStateEnum.SIGN_SUCCESS.getValue().equals(tbAgentEnterApplyPo.getState())) {
                Throw.isBusinessException("请先签约");
            }

            String hfId = tbAgentEnterApplyPo.getHfId();
            String certNo = tbAgentEnterApplyPo.getCertNo();
            Integer certValidityType = tbAgentEnterApplyPo.getCertValidityType();
            String certBeginDate = tbAgentEnterApplyPo.getCertBeginDate();
            String certEndDate = tbAgentEnterApplyPo.getCertEndDate();

            if (StringUtils.isBlank(hfId)) {
                log.error("经纪人更新银行卡失败，hfId为空，userId：{}，tbAgentEnterApplyPoId：{}", userId, tbAgentEnterApplyPo.getId());
                Throw.isBusinessException("修改失败，请联系客服");
            }

            LocalDateTime nowLocalDateTime = LocalDateUtil.getNowLocalDateTime();
            String yyyyMMdd = LocalDateUtil.toLocalDateToString(nowLocalDateTime.toLocalDate(), "yyyyMMdd");
            String reqSeqId = LocalDateUtil.toLocalDateTimeToString(nowLocalDateTime, "yyyyMMddHHmmss") + GenerateUtil.getRandomNum(5);

            // 调用汇付的用户业务入驻修改接口
            HfAgentUserEnterApply hfAgentUserEnterApply = new HfAgentUserEnterApply();
            hfAgentUserEnterApply.setReqSeqId(reqSeqId);
            hfAgentUserEnterApply.setReqDate(yyyyMMdd);
            hfAgentUserEnterApply.setHfId(hfId);
            hfAgentUserEnterApply.setCardName(cardName);
            hfAgentUserEnterApply.setCardNo(cardNo);
            hfAgentUserEnterApply.setCertNo(certNo);
            hfAgentUserEnterApply.setCertValidityType(certValidityType);
            hfAgentUserEnterApply.setCertBeginDate(certBeginDate);
            hfAgentUserEnterApply.setCertEndDate(certEndDate);
            hfAgentUserEnterApply.setMobileNo(mobile);
            hfAgentUserEnterApply.setBankProvinceCode(bankProvinceCode);
            hfAgentUserEnterApply.setBankCityCode(bankCityCode);

            JSONObject jsonObject = hfApi.agentUserModify(hfAgentUserEnterApply).unpack();
            if (jsonObject == null) {
                log.error("经纪人更新银行卡失败，调用hf接口失败，userId：{}，hfAgentUserEnterApply：{}", userId, JSON.toJSONString(hfAgentUserEnterApply));
                Throw.isBusinessException("修改失败，请联系客服");
            }

            JSONObject dataJSONObject = jsonObject.getJSONObject("data");
            String respCode = dataJSONObject.getString("resp_code");
            String respDesc = dataJSONObject.getString("resp_desc");
            if (!"00000000".equals(respCode)) {
                log.error("经纪人更新银行卡失败，调用hf接口失败，userId：{}，respDesc：{}", userId, respDesc);
                Throw.isBusinessException(respDesc);
            }

            String tokenNo = dataJSONObject.getString("token_no");
            if (StringUtils.isBlank(tokenNo)) {
                log.error("经纪人更新银行卡失败，调用hf接口成功但hf返回tokenNo为空，userId：{}，respDesc：{}", userId, respDesc);
                Throw.isBusinessException("修改失败，请联系客服");
            }

            // 汇付返回成功，添加修改记录
            TbAgentBankUpdateRecordPo tbAgentBankUpdateRecordPo = new TbAgentBankUpdateRecordPo();
            BeanUtils.copyProperties(tbAgentEnterApplyPo, tbAgentBankUpdateRecordPo);
            tbAgentBankUpdateRecordPo.setUserId(userId);
            tbAgentBankUpdateRecordPo.setApplyNo(NoUtils.getAgentUpdateBankApplyNo());
            tbAgentBankUpdateRecordPo.setCardName(cardName);
            tbAgentBankUpdateRecordPo.setCardNo(cardNo);
            tbAgentBankUpdateRecordPo.setBankProvinceCode(bankProvinceCode);
            tbAgentBankUpdateRecordPo.setBankProvinceName(bankProvinceName);
            tbAgentBankUpdateRecordPo.setBankCityCode(bankCityCode);
            tbAgentBankUpdateRecordPo.setBankCityName(bankCityName);
            tbAgentBankUpdateRecordPo.setHfId(hfId);
            tbAgentBankUpdateRecordPo.setTokenNo(tokenNo);
            tbAgentBankUpdateRecordPo.setReqSeqId(reqSeqId);
            tbAgentBankUpdateRecordPo.setReqDate(yyyyMMdd);
            tbAgentBankUpdateRecordPo.setApplyTime(nowLocalDateTime);
            tbAgentBankUpdateRecordPo.setAuditState(AuditStateEnum.SUCCESS.getValue());
            tbAgentBankUpdateRecordPo.setApplyIp(agentUpdateBankInfoDto.getApplyIp());
            tbAgentBankUpdateRecordPo.setCreateTime(nowLocalDateTime);
            tbAgentBankUpdateRecordPo.setUpdateTime(nowLocalDateTime);

            if (agentBankUpdateRecordMapper.insert(tbAgentBankUpdateRecordPo) == 0) {
                log.error("经纪人更新银行卡失败，保存修改记录失败，userId：{}，tbAgentBankUpdateRecordPo：{}", userId, JSON.toJSONString(tbAgentBankUpdateRecordPo));
                Throw.isBusinessException("修改失败，请联系客服");
            }

            return true;
        } finally {
            LockUtils.unlock(lockKey);
        }
    }
}
